/**
 * @author Ahammer
 * @date    2009 12
 * @update 2011 01 added 16 bit support
 */

/*
 * This file is part of Iqm.
 * Copyright (c) 2010-2011 Helmut Ahammer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package op;

import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import javax.media.jai.JAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.ROIShape;
import javax.media.jai.RenderedOp;

import main.Board;
import main.IqmTools;

/**
 * This is the main image processing class
 * There exist two approaches:
 * A user defined JAI operator is just called 
 * or:
 * The actual processing is implemented in this class 
 */
public class IqmWhiteBalanceOperator{ 


	public IqmWhiteBalanceOperator() {
		//WARNING: Don't declare fields here
		//Fields declared here aren't thread safe!   
	}

	/**
	 * 
	 * @param ParametrBlockJAI pb
	 */
	public Object run(ParameterBlockJAI pbJAI){
		//Calculation:   Image/(Mean of ROI) * 255
		//RenderingHints rh = IqmTools.getDefaultTileCacheRenderingHints();	    
		//Object ob = JAI.create("IqmWhiteBalance".toLowerCase(), pbJAI, null);	  
		
		Object ob = null;
	    PlanarImage pi = (PlanarImage) pbJAI.getSource(0);
	    int numBands = pi.getNumBands();
		int method   = pbJAI.getIntParameter("Method"); 
		int inR      = pbJAI.getIntParameter("InR");
		int inG      = pbJAI.getIntParameter("InG");
		int inB      = pbJAI.getIntParameter("InB");
		int outR     = pbJAI.getIntParameter("OutR");
		int outG     = pbJAI.getIntParameter("OutG");
		int outB     = pbJAI.getIntParameter("OutB");
		
		String type = IqmTools.getImgTyp(pi);
		double typeGreyMax = IqmTools.getImgTypeGreyMax(pi);  	
		
		double[] out  = new double[]{(double)outR, (double)outG, (double)outB};
	 
	 	ROIShape roi = IqmTools.getLookDisplayJAI().getCurrROIShape();
	 	if (method == 0){ //ROI	 		
			if (roi == null) {			
				Board.appendTexln("IqmWhiteBalanceOperator: ROI is not defined and null!");
				Board.appendTexln("IqmWhiteBalanceOperator: calculation with whole image!");
			}
			else{
				Board.appendTexln("IqmWhiteBalanceOperator: ROI is defined and valid");		
			}
	 	}
	    
	    ParameterBlock pb = new ParameterBlock();
		pb.addSource(pi);			
		pb.add(DataBuffer.TYPE_FLOAT);  
		pi = JAI.create("format",  pb);
		
		double[] mean = null;
		if (method == 0){ //ROI
			pb.removeSources();
			pb.removeParameters();
		    pb.addSource(pi);   
		    pb.add(roi); // ROI
		    pb.add(1);          			//sampling
		    pb.add(1);         
		    RenderedOp meanOp = JAI.create("Mean", pb, null);
		    mean = (double[])meanOp.getProperty("mean");
		}
		if (method == 1){ //Manual	
			mean = new double[]{(double)inR,  (double)inG,  (double)inB};
		}
		
	    					 Board.appendTexln("IqmWhiteBalanceOperator: ROI Mean of Band 0 = " + mean[0]);
	    if (mean.length > 1) Board.appendTexln("IqmWhiteBalanceOperator: ROI Mean of Band 1 = " + mean[1]);
	    if (mean.length > 2) Board.appendTexln("IqmWhiteBalanceOperator: ROI Mean of Band 2 = " + mean[2]);
	    						    
		pb.removeSources();
		pb.removeParameters();
	    pb.addSource(pi);   
	    pb.add(mean);          			
	    pi = JAI.create("DivideByConst", pb, null);

		pb.removeSources();
		pb.removeParameters();
		pb.addSource(pi);	
		//pb.add(new double[] {255});
		pb.add(out);
		pi = JAI.create("MultiplyConst", pb);
	
		pb.removeSources();
		pb.removeParameters();
		pb.addSource(pi);			
		if (type == "RGB")    pb.add(DataBuffer.TYPE_BYTE);  
		if (type == "8 bit")  pb.add(DataBuffer.TYPE_BYTE);  
		if (type == "16 bit") pb.add(DataBuffer.TYPE_USHORT);  
		pi = JAI.create("Format",  pb);
	
		ob = pi;    
	    return ob;
	}
}
